package io.summer.gateway.config;

import io.summer.gateway.handler.MyErrorWebExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;

import java.util.Collections;
import java.util.List;

/**
 * @author Moonlight
 */
@Configuration
@EnableConfigurationProperties({ServerProperties.class, WebProperties.class})
public class MyWebExceptionConfig {
  private final ServerProperties serverProperties;
  private final ApplicationContext applicationContext;
  private final WebProperties webProperties;
  private final List<ViewResolver> viewResolvers;
  private final ServerCodecConfigurer serverCodecConfigurer;

  public MyWebExceptionConfig(final ServerProperties serverProperties,
                              final WebProperties webProperties,
                              final ObjectProvider<List<ViewResolver>> viewResolversProvider,
                              final ServerCodecConfigurer serverCodecConfigurer,
                              final ApplicationContext applicationContext) {
    this.serverProperties = serverProperties;
    this.applicationContext = applicationContext;
    this.webProperties = webProperties;
    this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
    this.serverCodecConfigurer = serverCodecConfigurer;
  }

  @Bean
  @Primary
  @Order
  public ErrorWebExceptionHandler errorWebExceptionHandler(final ErrorAttributes errorAttributes) {
    final MyErrorWebExceptionHandler exceptionHandler = new MyErrorWebExceptionHandler(
      errorAttributes,
      this.webProperties,
      this.serverProperties.getError(),
      this.applicationContext);
    exceptionHandler.setViewResolvers(viewResolvers);
    exceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters());
    exceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders());
    return exceptionHandler;
  }
}
